{ This is a plug-in filters specifically designed for GraphicsMagic.
  Copyright (C) 2008 Ma Xiaoguang & Ma Xiaoming < gmbros@hotmail.com >,
  all rights reserved.}

unit AddNoiseDlg;

interface

uses
{ Standard }
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons,
{ Graphics32 }
  GR32, GR32_RangeBars,
{ GraphicsMagic Lib }
  gmAddNoise, gmTypes;

type
  TUpdateViewProc = procedure;

  TfrmAddNoise = class(TForm)
    GroupBox1: TGroupBox;
    lblAmount: TLabel;
    edtAmount: TEdit;
    ggbrAmount: TGaugeBar;
    btbtnOK: TBitBtn;
    btbtnCancel: TBitBtn;
    chckbxPreview: TCheckBox;
    chckbxMonochromatic: TCheckBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure btbtnOKClick(Sender: TObject);
    procedure ggbrAmountChange(Sender: TObject);
    procedure ggbrAmountMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ggbrAmountMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure chckbxPreviewClick(Sender: TObject);
    procedure edtAmountChange(Sender: TObject);
    procedure chckbxMonochromaticClick(Sender: TObject);
  private
    FAllowChange: Boolean;
    FNoiseMode  : TgmNoiseMode;
    
    procedure ExecuteAddNoise;
  public
    FSourceBmp     : TBitmap32;
    FProcessedBmp  : TBitmap32;
    FDestBmpPtr    : PColor32;
    FUpdateViewProc: TUpdateViewProc;
    FChannelSet    : TgmChannelSet;
  end;

procedure AddNoiseExecuteAddNoise(//FSourceBmp: TBitmap32;
  FChannelSet: TgmChannelSet;
  //FUpdateViewProc: TUpdateViewProc;
  FDestBmpPtr: PColor32;
  Width, Height : Integer;
  AParamsStr: string);
  
var
  frmAddNoise: TfrmAddNoise;

implementation

uses
{ Standard }
  IniFiles,
{ GraphicsMagic Lib }
  gmPluginFuncs, gmImageProcessFuncs,
  gmFilterBridges ;

{$R *.dfm}

const
  INI_SECTION                = 'AddNoiseSettings';
  INI_IDENT_ADD_NOISE_AMOUNT = 'Amount';
  INI_IDENT_NOISE_MODE       = 'NoiseMode';
  INI_IDENT_PREVIEW          = 'Preview';


procedure AddNoiseExecuteAddNoise(//FProcessedBmp: TBitmap32;
  FChannelSet: TgmChannelSet;
  //FUpdateViewProc: TUpdateViewProc;
  FDestBmpPtr: PColor32;
  Width, Height : Integer;
  AParamsStr: string);
var
  LColorChannelCount: Integer;
  LParams : TgmParamArray;
  FProcessedBmp : TBitmap32;
{  FSourceBmp    := TBitmap32.Create;
  FProcessedBmp := TBitmap32.Create;

  FDestBmpPtr     := nil;
  FUpdateViewProc := nil;
  FAllowChange    := True;
  FChannelSet     := [csRed, csGreen, csBlue];
}
begin
//  Screen.Cursor := crHourGlass;
  LParams := ParamArray(AParamsStr);
  FProcessedBmp := TBitmap32.Create;
  CopyBmpDataFromPtr(FDestBmpPtr, Width, Height, FProcessedBmp);
  try
    //FProcessedBmp.Assign(FSourceBmp);

    if LParams['Monochromatic'] = False then
    //case FNoiseMode of
      //nmColor:
        begin
          //AddColorNoise32(FProcessedBmp, ggbrAmount.Position);
          AddColorNoise32(FProcessedBmp, LParams['Amount']);
        end
    else
      //nmMono:
        begin
          //AddMonoNoise32(FProcessedBmp, ggbrAmount.Position);
          AddMonoNoise32(FProcessedBmp, LParams['Amount']);
        end;
    //end;

    if csGrayscale in FChannelSet then
    begin
      Desaturate32(FProcessedBmp);
    end
    else
    begin
      {LColorChannelCount := GetColorChannelCount(FChannelSet);

      if (LColorChannelCount > 0) and (LColorChannelCount < 3) then
      begin
        ReplaceRGBChannels(FSourceBmp, FProcessedBmp, FChannelSet, crsRemainDest);
      end;}
    end;

    //if chckbxPreview.Checked then
    begin
      CopyBmpDataToPtr(FProcessedBmp, FDestBmpPtr, FProcessedBmp.Width, FProcessedBmp.Height);

      {if Assigned(FUpdateViewProc) then
      begin
        FUpdateViewProc;
      end;}
    end;
  finally
   // Screen.Cursor := crDefault;
    FProcessedBmp.Free;
    LParams.Free;
  end;
end;



procedure TfrmAddNoise.ExecuteAddNoise;
var
  LColorChannelCount: Integer;
begin
  Screen.Cursor := crHourGlass;
  try
    FProcessedBmp.Assign(FSourceBmp);

    case FNoiseMode of
      nmColor:
        begin
          AddColorNoise32(FProcessedBmp, ggbrAmount.Position);
        end;

      nmMono:
        begin
          AddMonoNoise32(FProcessedBmp, ggbrAmount.Position);
        end;
    end;

    if csGrayscale in FChannelSet then
    begin
      Desaturate32(FProcessedBmp);
    end
    else
    begin
      LColorChannelCount := GetColorChannelCount(FChannelSet);

      if (LColorChannelCount > 0) and (LColorChannelCount < 3) then
      begin
        ReplaceRGBChannels(FSourceBmp, FProcessedBmp, FChannelSet, crsRemainDest);
      end;
    end;

    if chckbxPreview.Checked then
    begin
      CopyBmpDataToPtr(FProcessedBmp, FDestBmpPtr, FProcessedBmp.Width, FProcessedBmp.Height);

      if Assigned(FUpdateViewProc) then
      begin
        FUpdateViewProc;
      end;
    end;
  finally
    Screen.Cursor := crDefault;
  end;
end;

procedure TfrmAddNoise.FormCreate(Sender: TObject);
begin
  FSourceBmp    := TBitmap32.Create;
  FProcessedBmp := TBitmap32.Create;

  FDestBmpPtr     := nil;
  FUpdateViewProc := nil;
  FAllowChange    := True;
  FChannelSet     := [csRed, csGreen, csBlue];
end;

procedure TfrmAddNoise.FormDestroy(Sender: TObject);
begin
  FSourceBmp.Free;
  FProcessedBmp.Free;

  FDestBmpPtr     := nil;
  FUpdateViewProc := nil;
end;

procedure TfrmAddNoise.FormShow(Sender: TObject);
var
  LIniFile : TIniFile;
  LDLLName : array [0..255] of Char;
  LFileName: string;
  LAmount  : Integer;
begin
  GetModuleFileName(hInstance, LDLLName, 256);

  LFileName := LDLLName;
  LFileName := ChangeFileExt(LFileName, '.ini');

  LIniFile := TIniFile.Create(LFileName);
  try
    LAmount               := LIniFile.ReadInteger(INI_SECTION, INI_IDENT_ADD_NOISE_AMOUNT, 0);
    FNoiseMode            := TgmNoiseMode( LIniFile.ReadInteger(INI_SECTION, INI_IDENT_NOISE_MODE, 0) );
    chckbxPreview.Checked := LIniFile.ReadBool(INI_SECTION, INI_IDENT_PREVIEW, True);
  finally
    LIniFile.Free;
  end;

  ggbrAmount.Position         := LAmount;
  chckbxMonochromatic.Checked := (FNoiseMode = nmMono);

  ExecuteAddNoise;
end;

procedure TfrmAddNoise.FormClose(Sender: TObject;
  var Action: TCloseAction);
var
  LIniFile : TIniFile;
  LDLLName : array [0..255] of Char;
  LFileName: string;
begin
  GetModuleFileName(hInstance, LDLLName, 256);

  LFileName := LDLLName;
  LFileName := ChangeFileExt(LFileName, '.ini');

  LIniFile := TIniFile.Create(LFileName);
  try
    LIniFile.WriteBool(INI_SECTION, INI_IDENT_PREVIEW, chckbxPreview.Checked);
  finally
    LIniFile.Free;
  end;
end;

procedure TfrmAddNoise.btbtnOKClick(Sender: TObject);
var
  LIniFile : TIniFile;
  LDLLName : array [0..255] of Char;
  LFileName: string;
begin
  GetModuleFileName(hInstance, LDLLName, 256);

  LFileName := LDLLName;
  LFileName := ChangeFileExt(LFileName, '.ini');

  LIniFile := TIniFile.Create(LFileName);
  try
    LIniFile.WriteInteger(INI_SECTION, INI_IDENT_ADD_NOISE_AMOUNT, ggbrAmount.Position);
    LIniFile.WriteInteger(INI_SECTION, INI_IDENT_NOISE_MODE, Ord(FNoiseMode));
  finally
    LIniFile.Free;
  end;
end;

procedure TfrmAddNoise.ggbrAmountChange(Sender: TObject);
begin
  edtAmount.Text := IntToStr(ggbrAmount.Position);

  if FAllowChange then
  begin
    ExecuteAddNoise;
  end;
end;

procedure TfrmAddNoise.ggbrAmountMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  FAllowChange := False;
end;

procedure TfrmAddNoise.ggbrAmountMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  ExecuteAddNoise;
  FAllowChange := True;
end;

procedure TfrmAddNoise.chckbxPreviewClick(Sender: TObject);
begin
  if chckbxPreview.Checked then
  begin
    CopyBmpDataToPtr(FProcessedBmp, FDestBmpPtr, FProcessedBmp.Width, FProcessedBmp.Height);

    if Assigned(FUpdateViewProc) then
    begin
      FUpdateViewProc;
    end;
  end;
end;

procedure TfrmAddNoise.edtAmountChange(Sender: TObject);
var
  LChangedValue: Integer;
begin
  try
    LChangedValue := StrToInt(edtAmount.Text);
    ClampValue(LChangedValue, ggbrAmount.Min, ggbrAmount.Max);

    ggbrAmount.Position := LChangedValue;
    edtAmount.Text      := IntToStr(ggbrAmount.Position);
  except
    edtAmount.Text := IntToStr(ggbrAmount.Position);
  end;
end;

procedure TfrmAddNoise.chckbxMonochromaticClick(Sender: TObject);
begin
  if chckbxMonochromatic.Checked then
  begin
    FNoiseMode := nmMono;
  end
  else
  begin
    FNoiseMode := nmColor;
  end;
  
  ExecuteAddNoise;
end;

end.
